<template>
	<view class="h-mark-upload">
		<!-- Canvas 容器 -->
		<view class="canvas-container">
			<canvas id="watermarkCanvas" canvas-id="watermarkCanvas" :style="{
					width: '1000px',
					height: '1000px'
				}"></canvas>
		</view>

		<!-- 图片列表 -->
		<view class="upload-list">
			<view class="upload-item" v-for="(item, index) in imageList" :key="index">
				<image :src="item.url" mode="aspectFill" @click="previewImage(index)" />
				<!-- 修改加载状态显示 -->
				<view class="loading-mask" v-if="item.loading">
					<view class="loading-content">
						<text class="loading-text">上传中...</text>
					</view>
				</view>
				<view class="delete-btn" @click.stop="deleteImage(index)" v-if="!item.loading">
					<u-icon name="close" color="#fff" size="20"></u-icon>
				</view>
			</view>

			<!-- 上传按钮 -->
			<view class="upload-btn" v-if="imageList.length < maxCount" @click="chooseImage">
				<u-icon name="camera-fill" size="40" color="#999"></u-icon>
				<text>上传图片</text>
			</view>
		</view>
	</view>
</template>

<script setup name='watermark-img'>
	/**
	 * 水印图片上传组件
	 * 
	 * 功能：
	 * 1. 支持从相册或相机选择图片
	 * 2. 自动添加包含用户信息、时间和位置的水印
	 * 3. 上传图片到服务器
	 * 4. 支持图片预览和删除
	 * 
	 * @property {Array} value - 绑定值，已上传的图片URL数组
	 * @property {Number} [maxCount=9] - 最大上传数量
	 * @property {String} [userName='未知用户'] - 水印显示的用户名
	 * 
	 * @event on-success - 上传成功事件，参数为上传成功的文件信息
	 * @event on-delete - 删除图片事件，参数为被删除的图片索引
	 * @event update:value - 双向绑定事件，参数为当前图片URL数组
	 */
	import {
		ref,
		watch,
		getCurrentInstance
	} from 'vue'
	import {
		onReady
	} from '@dcloudio/uni-app'

	const props = defineProps({
		value: {
			type: Array,
			default: () => []
		},
		maxCount: {
			type: Number,
			default: 9
		},
		userName: {
			type: String,
			default: '未知用户'
		}
	})

	const emit = defineEmits(['update:value', 'on-success', 'on-delete'])

	const imageList = ref([])
	const tempImagePath = ref('')
	const watermarkedPath = ref('')

	// 监听props.value变化
	watch(() => props.value, (newVal) => {
		imageList.value = newVal.map(url => ({
			url
		}))
	}, {
		immediate: true
	})

	// 选择图片
	const chooseImage = () => {
		uni.chooseImage({
			count: 1,
			sizeType: ['compressed'], // 使用压缩模式
			sourceType: ['camera', 'album'],
			success: async (res) => {
				try {
					tempImagePath.value = res.tempFilePaths[0]; // 改为使用 ref
					const imageInfo = await getImageInfo(tempImagePath.value);
					const locationInfo = await getLocation();
					await addWatermark(tempImagePath.value, locationInfo.address, imageInfo);

					if (watermarkedPath.value) { // 改为使用 ref
						uploadImage(watermarkedPath.value);
					}
				} catch (error) {
					uni.$u.toast('处理图片失败');
				}
			}
		});
	}

	// 获取图片信息
	const getImageInfo = (imagePath) => {
		return new Promise((resolve, reject) => {
			uni.getImageInfo({
				src: imagePath,
				success: (imageInfo) => resolve(imageInfo),
				fail: (error) => reject(error)
			});
		});
	}

	// 添加水印（修正DOM操作部分）
	const addWatermark = async (imagePath, location, imageInfo) => {
		return new Promise((resolve, reject) => {
			const query = uni.createSelectorQuery().in(instance)
			query.select('#watermarkCanvas').boundingClientRect(rect => {
				if (rect) {
					rect.style.width = canvasWidth + 'px'
					rect.style.height = canvasHeight + 'px'
				}
			}).exec()
			const instance = getCurrentInstance(); // 获取组件实例
			const ctx = uni.createCanvasContext('watermarkCanvas', instance); // 使用组件实例

			// 限制最大尺寸为较小的值，减小输出文件大小
			const maxSize = 600; // 从800降到600
			let canvasWidth = imageInfo.width;
			let canvasHeight = imageInfo.height;

			// 更积极的尺寸压缩
			if (canvasWidth > maxSize || canvasHeight > maxSize) {
				const ratio = Math.min(maxSize / canvasWidth, maxSize / canvasHeight);
				canvasWidth = Math.floor(canvasWidth * ratio);
				canvasHeight = Math.floor(canvasHeight * ratio);
			}

			// 更新canvas尺寸
			const canvasNode = this.$el.querySelector('#watermarkCanvas');
			if (canvasNode) {
				canvasNode.style.width = canvasWidth + 'px';
				canvasNode.style.height = canvasHeight + 'px';
			}

			// 清空画布并绘制图片
			ctx.clearRect(0, 0, canvasWidth, canvasHeight);
			ctx.drawImage(imagePath, 0, 0, canvasWidth, canvasHeight);

			// 设置更大的基础字体大小
			const fontSize = Math.max(16, Math.floor(canvasWidth * 0.035)); // 增加字体大小
			ctx.setFontSize(fontSize);

			// 准备水印文本
			const watermarkTexts = [
				`上传人：${props.userName}`, // 使用 props
				`时间：${formatTime()}`,
				`位置：${location}`
			];

			// 计算文本宽度
			let maxTextWidth = 0;
			watermarkTexts.forEach(text => {
				const textWidth = ctx.measureText(text).width;
				maxTextWidth = Math.max(maxTextWidth, textWidth);
			});

			// 计算水印区域大小
			const padding = fontSize;
			const lineHeight = fontSize * 1.5;
			const watermarkWidth = maxTextWidth + padding * 2;
			const watermarkHeight = lineHeight * watermarkTexts.length + padding;

			// 水印位置（右下角）
			const watermarkX = canvasWidth - watermarkWidth - padding;
			const watermarkY = canvasHeight - watermarkHeight - padding;

			// 绘制半透明背景（只在文字区域）
			ctx.setFillStyle('rgba(255, 255, 255, 0.6)');
			ctx.fillRect(watermarkX, watermarkY, watermarkWidth, watermarkHeight);

			// 绘制文字
			ctx.setFillStyle('#333333');
			watermarkTexts.forEach((text, index) => {
				ctx.fillText(
					text,
					watermarkX + padding,
					watermarkY + padding + lineHeight * index + fontSize
				);
			});

			ctx.draw(false, () => {
				uni.canvasToTempFilePath({
					canvasId: 'watermarkCanvas',
					success: (res) => {
						watermarkedPath.value = res.tempFilePath // 使用ref
						resolve()
					},
					fail: reject
				}, instance) // 传入组件实例
			})
		})
	}

	// 获取位置信息
	const getLocation = async () => {
		try {
			// 先获取精确定位权限和经纬度
			const [error, location] = await uni.getLocation({
				type: 'gcj02', // 使用国测局坐标系
				isHighAccuracy: true, // 开启高精度定位
			}).catch(err => [err]);

			if (error) {
				throw new Error('获取位置失败');
			}

			// 通过经纬度解析详细地址
			const res = await $U.jsonp('https://apis.map.qq.com/ws/geocoder/v1/', {
				key: $C.txMapKEY,
				location: `${location.latitude},${location.longitude}`,
				output: "jsonp"
			});

			if (res.status === 0) {
				const addressInfo = res.result.address_component;
				// console.log('地图',addressInfo)
				return {
					address: `${addressInfo.province}-${addressInfo.city}-${addressInfo.district}`
				};
			} else {
				throw new Error('地址解析失败');
			}
		} catch (error) {
			console.error('位置获取失败:', error);
			return {
				address: '未知位置'
			};
		}
	}

	// 格式化时间
	const formatTime = () => {
		const date = new Date()
		return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`
	}

	// 上传图片
	const uploadImage = (filePath) => {
		const tempFileInfo = {
			url: filePath,
			loading: true
		}
		const currentIndex = imageList.value.length
		imageList.value.push(tempFileInfo)
		uni.getFileInfo({
			filePath: filePath,
			success: (res) => {
				const fileSize = res.size / 1024
				console.log('文件大小:', fileSize, 'KB')

				uni.uploadFile({
					url: $C.fileUpload,
					filePath: filePath,
					name: 'multipartFile',
					header: {
						'Authorization': getToken(),
					},
					success: (res) => {
						const ajaxData = JSON.parse(res.data)
						if (ajaxData.code == 200) {
							const fileInfo = {
								fileId: ajaxData.data.fileId,
								url: ajaxData.data.fileInternetAddress,
								loading: false
							}
							imageList.value[currentIndex] = fileInfo
							emit('input', imageList.value.map(item => item.url))
							emit('on-success', fileInfo)
						} else {
							imageList.value.splice(currentIndex, 1)
							uni.$u.toast(ajaxData.msg || '上传失败')
						}
					},
					fail: (error) => {
						imageList.value.splice(currentIndex, 1)
						console.error('上传失败:', error)
						uni.$u.toast('上传失败')
					}
				})
			},
			fail: (error) => {
				imageList.value.splice(currentIndex, 1)
				console.error('获取文件信息失败:', error)
				uni.$u.toast('文件读取失败')
			}
		})
	}

	// 预览图片
	const previewImage = (index) => {
		uni.previewImage({
			urls: imageList.value.map(item => item.url),
			current: index
		})
	}

	// 删除图片
	const deleteImage = (index) => {
		uni.showModal({
			title: '提示',
			content: '确定要删除这张图片吗？',
			success: (res) => {
				if (res.confirm) {
					imageList.value.splice(index, 1)
					emit('input', imageList.value.map(item => item.url))
					emit('on-delete', index)
				}
			}
		})
	}
</script>

<style lang="scss" scoped>
	.h-mark-upload {
		.canvas-container {
			position: fixed;
			left: -9999px;
			top: -9999px;
			z-index: -1;
		}

		.upload-list {
			display: flex;
			flex-wrap: wrap;
			gap: 20rpx;
			margin-bottom: 30rpx;

			.upload-item {
				position: relative;
				width: 200rpx;
				height: 200rpx;
				border-radius: 8rpx;
				overflow: hidden;
				background-color: #f5f7fa;

				image {
					width: 100%;
					height: 100%;
					object-fit: cover;
				}

				.loading-mask {
					position: absolute;
					top: 0;
					left: 0;
					right: 0;
					bottom: 0;
					background-color: rgba(0, 0, 0, 0.5);
					display: flex;
					align-items: center;
					justify-content: center;
					z-index: 2;

					.loading-content {
						display: flex;
						flex-direction: column;
						align-items: center;

						.loading-text {
							color: #ffffff;
							font-size: 24rpx;
						}
					}
				}

				.delete-btn {
					position: absolute;
					top: 10rpx;
					right: 10rpx;
					width: 40rpx;
					height: 40rpx;
					background-color: rgba(0, 0, 0, 0.5);
					border-radius: 50%;
					display: flex;
					align-items: center;
					justify-content: center;
					z-index: 1;
				}
			}

			.upload-btn {
				width: 200rpx;
				height: 200rpx;
				background-color: #f5f7fa;
				border: 2rpx dashed #dcdfe6;
				border-radius: 8rpx;
				display: flex;
				flex-direction: column;
				align-items: center;
				justify-content: center;

				text {
					font-size: 24rpx;
					color: #999;
					margin-top: 10rpx;
				}
			}
		}
	}
</style>